import java.net.*;
import java.io.*;
import java.util.*;

// Simple Multi Chatting Server
public class TestServer extends Thread
{
	private ServerSocket ss;
	private Socket s;
	private int port;
	private String host;
	private Vector<ServiceToOneClient> v;
	private ServiceToOneClient stoc;
	private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

	TestServer()
	{
		ready();
	}

	private void ready()
	{
		try{
			input();
			v = new Vector<ServiceToOneClient>();
			ss = new ServerSocket(port);
			System.out.println("Waiting from client connetting....");
			start();
			while (true)
			{
				s = ss.accept();
				System.out.print("");
				// Thread - communication with client
				stoc = new ServiceToOneClient(s, this);
				v.add(stoc);
				stoc.start();
			}
		}catch (IOException ie){
		}finally{
			try{
				if(ss != null) ss.close();
			}catch (IOException ie){}
		}
	}

	private void input()
	{
		try{
			System.out.print("Waiting PORT(default:7000) : ");
			String portStr = br.readLine();
			if(portStr != null) portStr = portStr.trim();
			if(portStr.equals("")) portStr = "7777";
			port = Integer.parseInt(portStr);
			if(port < 0 || port > 65535)
			{
				System.out.println("Port number has to be 0~65535.");
				input();
			}
			System.out.println("PORT : " + port);
		}catch (IOException ie){
			System.out.println("wrong input value.");
			input();
		}catch (NumberFormatException ne){
			System.out.println("You can input only number in port.");
			input();
		}
	}

	public void run()
	{
		ServiceToOneClient stoc = null;
		String serverMsg = "";
		try{
			while (true)
			{
				serverMsg = br.readLine();
				if(v.size() > 0)
				{
					stoc = v.elementAt(0);
					stoc.broadcast("Server>> " + serverMsg);
				}else{
					System.out.println("Client is not exist.");
				}
			}
		}catch (IOException e){}
	}

	public Vector getV()
	{
		return v;
	}

	public static void main(String[] args) 
	{
		new TestServer();
	}
}

// Server class which takes each one client
class ServiceToOneClient extends Thread
{
	private TestServer server;
	private Socket s;
	private Vector v;
	private String client_id = "Client";
	private InputStream is;
	private OutputStream os;
	private DataInputStream dis;
	private PrintStream dos;

	ServiceToOneClient() {}

	ServiceToOneClient(Socket s, TestServer server)
	{
		this.s = s;
		this.server = server;
		v = server.getV();
		try{
			is = s.getInputStream();
			dis = new DataInputStream(is);
			os = s.getOutputStream();
			dos = new PrintStream(os);
		}catch (IOException ie){}
	}

	public void run() // Read from socket and write(own & connected client)
	{
		String msg = "";
		try{
			client_id = dis.readLine();
			System.out.println(client_id +" Enter!! " + "(Current number of member : " + v.size() + ")");
			broadcast(client_id+"|");
//			while(true)
//			{	
//				msg = dis.readLine();
//				System.out.println(client_id + ">> " + msg); // Print out in server console
//				broadcast(client_id + ">> " + msg); // Print out in client console
//			}
		}catch (IOException ie){
			v.remove(this);
			System.out.println("ID "+client_id +" Out!! " + "(Current number of member : " + v.size() + ")");
			broadcast("ID "+client_id +" Out!! " + "(Current number of member : " + v.size() + ")");
			allClose();
		}
	}

	public void broadcast(String msg)
	{
		ServiceToOneClient stoc = null;
		PrintStream dos = null;
		Enumeration<ServiceToOneClient> e = v.elements();
		while(e.hasMoreElements())
		{
			stoc = e.nextElement();
			dos = stoc.getDos();
			dos.print(stoc.client_id+"|");
		}
		if(dos != null){
			dos.println();
			dos.flush();
		}
	}

	private void allClose()
	{
		try{
			if(dos != null) dos.close();
			if(os != null) os.close();
			if(dis != null) dis.close();
			if(is != null) is.close();
			if(s != null) s.close();
		}catch (IOException ie){}
	}

	private PrintStream getDos()
	{
		return dos;
	}
}